package demo1;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

public class MyTimer {
    BlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    public void schedule(Runnable runnable, long delay) throws InterruptedException {
        MyTask myTask = new MyTask(runnable, delay);
        queue.put(myTask);
        synchronized (this) {
            this.notifyAll();
        }
    }

    public MyTimer() {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    MyTask myTask = queue.take();
                    long time = System.currentTimeMillis();
                    //时间到了就执行，没有到就放回去继续等待
                    if (time >= myTask.getTime()) {
                        myTask.getRunnable().run();
                    } else {
                        queue.put(myTask);
                        synchronized (this) {
                            this.wait( myTask.getTime()-time);
                        }

                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
        thread.start();
        //为了让他可以被及时唤醒我们加一个后台线程来保证其及时被唤醒
        Thread t1 =new Thread(()->{
            while (true) {
                synchronized (this){
                    this.notifyAll();
                }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.setDaemon(true);
        t1.start();
    }
}

class MyTask implements Comparable<MyTask> {
    private Runnable runnable;
    private long time;

    public MyTask(Runnable runnable, long delay) {
        this.runnable = runnable;
        time = System.currentTimeMillis() + delay;
    }

    public Runnable getRunnable() {
        return runnable;
    }

    public void setRunnable(Runnable runnable) {
        this.runnable = runnable;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    @Override
    public int compareTo(MyTask o) {
        if (this.time - o.getTime() > 0) return 1;
        else if (this.time - o.getTime() < 0) return -1;
        else return 0;
    }
}
